package org.jflame.context.security.mask.jackson;

import org.jflame.context.security.mask.Mask;
import org.jflame.context.security.mask.MaskHandler;

import java.io.IOException;
import java.util.Objects;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;

/**
 * jackson脱敏注解序列化处理器
 * 
 * @author charles.zhang
 * @see Mask
 * @see JacksonMask
 */
public class MaskedSerializer extends JsonSerializer<String> implements ContextualSerializer {

    private MaskHandler converter;

    public MaskedSerializer() {
    }

    public MaskedSerializer(MaskHandler converter) {
        this.converter = converter;
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
            throws JsonMappingException {
        // 使用@JacksonMask注解
        JacksonMask jacksonMaskAnnot = property.getAnnotation(JacksonMask.class);
        if (jacksonMaskAnnot == null) {
            jacksonMaskAnnot = property.getContextAnnotation(JacksonMask.class);
        }
        if (Objects.nonNull(jacksonMaskAnnot) && Objects.equals(String.class, property.getType()
                .getRawClass())) {
            return new MaskedSerializer(MaskHandler.build(jacksonMaskAnnot));
        }
        // 使用@Mask+@JsonSerialize注解
        Mask maskAnnot = property.getAnnotation(Mask.class);
        if (maskAnnot == null) {
            maskAnnot = property.getContextAnnotation(Mask.class);
        }
        if (Objects.nonNull(maskAnnot) && Objects.equals(String.class, property.getType()
                .getRawClass())) {
            return new MaskedSerializer(MaskHandler.build(maskAnnot));
        }

        return prov.findValueSerializer(property.getType(), property);
    }

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(converter != null ? converter.apply(value) : value);
    }

}
